using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Linq;

namespace ScreenKeyboardTester
{
    // 全局键盘钩子类
    public class GlobalKeyboardHook : IMessageFilter
    {
        private KeyboardTestPanel parentPanel;
        
        public GlobalKeyboardHook(KeyboardTestPanel panel)
        {
            parentPanel = panel;
        }
        
        public bool PreFilterMessage(ref Message m)
        {
            const int WM_KEYDOWN = 0x100;
            const int WM_KEYUP = 0x101;
            const int WM_SYSKEYDOWN = 0x104;
            const int WM_SYSKEYUP = 0x105;
            
            if (m.Msg == WM_KEYDOWN || m.Msg == WM_SYSKEYDOWN)
            {
                Keys key = (Keys)(int)m.WParam;
                bool shift = (Control.ModifierKeys & Keys.Shift) != 0;
                bool control = (Control.ModifierKeys & Keys.Control) != 0;
                bool alt = (Control.ModifierKeys & Keys.Alt) != 0;
                
                parentPanel.HandleGlobalKeyDown(key, shift, control, alt);
            }
            else if (m.Msg == WM_KEYUP || m.Msg == WM_SYSKEYUP)
            {
                Keys key = (Keys)(int)m.WParam;
                parentPanel.HandleGlobalKeyUp(key);
            }
            
            return false; // 允许消息继续传递
        }
    }
    
    public class KeyboardTestPanel : Panel
    {
        private TextBox? keyLogTextBox;
        private Button? clearButton;
        private Button? startButton;
        private Button? stopButton;
        private Panel? keyStatusPanel;
        private Label? instructionLabel;
        private Dictionary<Keys, Label>? keyLabels;
        private bool isTesting = false;
        private HashSet<Keys> pressedKeys = new HashSet<Keys>();
        private RichTextBox? historyLogTextBox; // 修改：改为RichTextBox以支持颜色显示
        private List<string> keyHistory = new List<string>(); // 新增：按键历史记录
        private Button? saveLogButton; // 新增：保存日志按钮
        private Button? autoSaveButton; // 新增：自动保存按钮
        private bool autoSaveEnabled = false; // 新增：自动保存开关
        private string autoSavePath = ""; // 新增：自动保存路径
        private int autoSaveCount = 0; // 新增：自动保存计数
        private GlobalKeyboardHook globalHook;

        public KeyboardTestPanel()
        {
            InitializeComponent();
            SetupKeyStatusPanel();
            
            // 默认开启自动保存
            autoSaveEnabled = true;
            autoSaveCount = 0;
            
            // 更新自动保存按钮状态
            if (autoSaveButton != null)
            {
                autoSaveButton.Text = "停止自动保存";
                autoSaveButton.BackColor = Color.LightGreen;
            }
            
            // 应用程序启动时自动开始键盘测试
            StartButton_Click(this, EventArgs.Empty);
        }

        private void InitializeComponent()
        {
            this.BackColor = SystemColors.Control;
            this.Dock = DockStyle.Fill; // 使面板填充整个选项卡

            // 指令标签
            instructionLabel = new Label
            {
                Location = new Point(20, 20),
                Size = new Size(400, 30),
                Text = "按下键盘上的任意按键进行测试，下方会显示按键状态和记录",
                Font = new Font("Microsoft YaHei", 10),
                Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right // 自适应宽度
            };

            // 开始按钮
            startButton = new Button
            {
                Location = new Point(20, 60),
                Size = new Size(80, 25),
                Text = "开始测试",
                Anchor = AnchorStyles.Top | AnchorStyles.Left
            };
            startButton.Click += StartButton_Click;

            // 停止按钮
            stopButton = new Button
            {
                Location = new Point(110, 60),
                Size = new Size(80, 25),
                Text = "停止测试",
                Enabled = false,
                Anchor = AnchorStyles.Top | AnchorStyles.Left
            };
            stopButton.Click += StopButton_Click;

            // 清空按钮
            clearButton = new Button
            {
                Location = new Point(200, 60),
                Size = new Size(80, 25),
                Text = "清空记录",
                Anchor = AnchorStyles.Top | AnchorStyles.Left
            };
            clearButton.Click += ClearButton_Click;

            // 保存日志按钮
            saveLogButton = new Button
            {
                Location = new Point(290, 60),
                Size = new Size(80, 25),
                Text = "保存日志",
                Anchor = AnchorStyles.Top | AnchorStyles.Left
            };
            saveLogButton.Click += SaveLogButton_Click;

            // 自动保存按钮
            autoSaveButton = new Button
            {
                Location = new Point(380, 60),
                Size = new Size(80, 25),
                Text = "自动保存",
                Anchor = AnchorStyles.Top | AnchorStyles.Left
            };
            autoSaveButton.Click += AutoSaveButton_Click;

            // 按键状态面板
            keyStatusPanel = new Panel
            {
                Location = new Point(20, 100),
                Size = new Size(760, 180),
                BorderStyle = BorderStyle.FixedSingle,
                AutoScroll = true,
                Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right // 自适应宽度
            };

            // 按键记录文本框
            keyLogTextBox = new TextBox
            {
                Location = new Point(20, 300),
                Size = new Size(760, 150),
                Multiline = true,
                ScrollBars = ScrollBars.Vertical,
                ReadOnly = true,
                Font = new Font("Consolas", 9), // 使用等宽字体便于对齐
                Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right // 自适应宽度
            };

            // 历史按键日志文本框（改为RichTextBox以支持颜色显示和滚屏）
            historyLogTextBox = new RichTextBox
            {
                Location = new Point(20, 470),
                Size = new Size(760, 200), // 增加高度以更好地显示滚屏效果
                Multiline = true,
                ScrollBars = RichTextBoxScrollBars.Vertical,
                ReadOnly = true,
                Font = new Font("Consolas", 9), // 使用等宽字体便于对齐
                Text = "历史按键日志（实时滚屏显示）：",
                WordWrap = false, // 禁用自动换行，便于查看长文本
                Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right // 自适应宽度和高度
            };

            // 添加控件
            this.Controls.Add(instructionLabel);
            this.Controls.Add(startButton);
            this.Controls.Add(stopButton);
            this.Controls.Add(clearButton);
            this.Controls.Add(saveLogButton);
            this.Controls.Add(autoSaveButton);
            this.Controls.Add(keyStatusPanel);
            this.Controls.Add(keyLogTextBox);
            this.Controls.Add(historyLogTextBox);
        }

        private void SetupKeyStatusPanel()
        {
            keyLabels = new Dictionary<Keys, Label>();
            
            // 定义要测试的常用按键
            var testKeys = new Keys[]
            {
                Keys.A, Keys.B, Keys.C, Keys.D, Keys.E, Keys.F, Keys.G, Keys.H, Keys.I, Keys.J,
                Keys.K, Keys.L, Keys.M, Keys.N, Keys.O, Keys.P, Keys.Q, Keys.R, Keys.S, Keys.T,
                Keys.U, Keys.V, Keys.W, Keys.X, Keys.Y, Keys.Z,
                Keys.D0, Keys.D1, Keys.D2, Keys.D3, Keys.D4, Keys.D5, Keys.D6, Keys.D7, Keys.D8, Keys.D9,
                Keys.Space, Keys.Enter, Keys.Back, Keys.Tab, Keys.CapsLock, Keys.Escape,
                Keys.Left, Keys.Right, Keys.Up, Keys.Down,
                Keys.LShiftKey, Keys.RShiftKey, Keys.LControlKey, Keys.RControlKey, Keys.LMenu, Keys.RMenu
            };

            int x = 10, y = 10;
            int labelWidth = 80;
            int labelHeight = 25;
            int spacing = 5;
            int maxWidth = keyStatusPanel != null ? keyStatusPanel.Width - 20 : 760; // 自适应面板宽度

            foreach (var key in testKeys)
            {
                var label = new Label
                {
                    Location = new Point(x, y),
                    Size = new Size(labelWidth, labelHeight),
                    Text = GetKeyDisplayName(key),
                    TextAlign = ContentAlignment.MiddleCenter,
                    BorderStyle = BorderStyle.FixedSingle,
                    BackColor = Color.LightGray,
                    Font = new Font("Microsoft YaHei", 9, FontStyle.Regular)
                };

                keyLabels[key] = label;
                if (keyStatusPanel != null) keyStatusPanel.Controls.Add(label);

                x += labelWidth + spacing;
                if (x + labelWidth > maxWidth)
                {
                    x = 10;
                    y += labelHeight + spacing;
                }
            }
        }

        private string GetKeyDisplayName(Keys key)
        {
            return key switch
            {
                Keys.LShiftKey => "左Shift",
                Keys.RShiftKey => "右Shift",
                Keys.LControlKey => "左Ctrl",
                Keys.RControlKey => "右Ctrl",
                Keys.LMenu => "左Alt",
                Keys.RMenu => "右Alt",
                Keys.D0 => "0", Keys.D1 => "1", Keys.D2 => "2", Keys.D3 => "3", Keys.D4 => "4",
                Keys.D5 => "5", Keys.D6 => "6", Keys.D7 => "7", Keys.D8 => "8", Keys.D9 => "9",
                Keys.Space => "空格",
                Keys.Enter => "回车",
                Keys.Back => "退格",
                Keys.Tab => "Tab",
                Keys.CapsLock => "大写",
                Keys.Escape => "Esc",
                Keys.Left => "←",
                Keys.Right => "→",
                Keys.Up => "↑",
                Keys.Down => "↓",
                _ => key.ToString()
            };
        }

        private void StopButton_Click(object sender, EventArgs e)
        {
            isTesting = false;
            if (startButton != null) startButton.Enabled = true;
            if (stopButton != null) stopButton.Enabled = false;
            
            // 记录停止前所有按下的键位
            if (keyLogTextBox != null)
            {
                var pressedKeyNames = pressedKeys.Select(k => GetKeyDisplayName(k)).ToArray();
                if (pressedKeyNames.Length > 0)
                {
                    keyLogTextBox.AppendText($"{DateTime.Now:HH:mm:ss.ffffff} - 停止测试时按下的键: {string.Join(", ", pressedKeyNames)}\r\n");
                }
                keyLogTextBox.AppendText("键盘测试结束。\r\n");
            }
            
            // 重置所有按键状态
            if (keyLabels != null)
            {
                foreach (var label in keyLabels.Values)
                {
                    label.BackColor = Color.LightGray;
                }
            }

            // 移除全局键盘钩子
            Application.RemoveMessageFilter(globalHook);
        }

        private void ClearButton_Click(object sender, EventArgs e)
        {
            if (keyLogTextBox != null) keyLogTextBox.Clear();
            
            // 清空历史按键日志
            keyHistory.Clear();
            if (historyLogTextBox != null)
            {
                historyLogTextBox.Clear();
                historyLogTextBox.AppendText("历史按键日志：");
            }
        }

        // 由于Panel不支持KeyPreview，我们需要通过其他方式捕获键盘事件
        // 在开始测试时，我们将设置焦点并处理键盘事件
        
        private void StartButton_Click(object sender, EventArgs e)
        {
            isTesting = true;
            pressedKeys.Clear(); // 清空按下的键集合
            keyHistory.Clear(); // 清空历史按键记录
            if (startButton != null) startButton.Enabled = false;
            if (stopButton != null) stopButton.Enabled = true;
            if (keyLogTextBox != null) keyLogTextBox.Text = "当前没有按下的键\r\n键盘测试开始...\r\n";
            
            // 重置历史按键日志
            if (historyLogTextBox != null)
            {
                historyLogTextBox.Text = "历史按键日志（实时滚屏显示）：";
            }
            
            // 重置所有按键状态
            if (keyLabels != null)
            {
                foreach (var label in keyLabels.Values)
                {
                    label.BackColor = Color.LightGray;
                }
            }

            // 注册全局键盘钩子
            globalHook = new GlobalKeyboardHook(this);
            Application.AddMessageFilter(globalHook);
        }

        public void HandleGlobalKeyDown(Keys key, bool shift, bool control, bool alt)
        {
            if (isTesting && keyLogTextBox != null && keyLabels != null)
            {
                // 添加按下的键到集合中
                if (!pressedKeys.Contains(key))
                {
                    pressedKeys.Add(key);
                }
                
                // 更新按键状态显示
                if (keyLabels.ContainsKey(key))
                {
                    keyLabels[key].BackColor = Color.LightGreen;
                }

                // 记录按键信息（包含微秒时间戳）
                string keyInfo = $"按下: {GetKeyDisplayName(key)} (KeyCode: {key}, KeyValue: {(int)key})";
                if (shift) keyInfo += " + Shift";
                if (control) keyInfo += " + Ctrl";
                if (alt) keyInfo += " + Alt";
                
                keyLogTextBox.AppendText($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.ffffff} - {keyInfo}\r\n");
                
                // 更新历史按键日志
                UpdateHistoryLog($"按下:{GetKeyDisplayName(key)}");
                
                // 更新第一行显示当前按下的所有键
                UpdatePressedKeysDisplay();
                
                // 自动保存日志
                AutoSaveLog();
                
                keyLogTextBox.SelectionStart = keyLogTextBox.Text.Length;
                keyLogTextBox.ScrollToCaret();
            }
        }

        public void HandleGlobalKeyUp(Keys key)
        {
            if (isTesting && keyLogTextBox != null && keyLabels != null)
            {
                // 从集合中移除释放的键
                if (pressedKeys.Contains(key))
                {
                    pressedKeys.Remove(key);
                }
                
                // 更新按键状态显示
                if (keyLabels.ContainsKey(key))
                {
                    keyLabels[key].BackColor = Color.LightGray;
                }

                keyLogTextBox.AppendText($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.ffffff} - 释放: {GetKeyDisplayName(key)}\r\n");
                
                // 更新历史按键日志
                UpdateHistoryLog($"释放:{GetKeyDisplayName(key)}");
                
                // 更新第一行显示当前按下的所有键
                UpdatePressedKeysDisplay();
                
                // 自动保存日志
                AutoSaveLog();
                
                keyLogTextBox.SelectionStart = keyLogTextBox.Text.Length;
                keyLogTextBox.ScrollToCaret();
            }
        }

        // 字符输入处理（由于全局钩子无法直接捕获字符输入，保留此方法但不再使用）
        public void HandleGlobalKeyChar(char keyChar)
        {
            if (isTesting && keyLogTextBox != null)
            {
                // 记录字符输入
                if (!char.IsControl(keyChar))
                {
                    keyLogTextBox.AppendText($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.ffffff} - 字符: '{keyChar}' (ASCII: {(int)keyChar})\r\n");
                    
                    // 更新历史按键日志
                    UpdateHistoryLog($"字符:'{keyChar}'");
                    
                    // 自动保存日志
                    AutoSaveLog();
                    
                    keyLogTextBox.SelectionStart = keyLogTextBox.Text.Length;
                    keyLogTextBox.ScrollToCaret();
                }
            }
        }

        private void UpdatePressedKeysDisplay()
        {
            if (keyLogTextBox != null && keyLogTextBox.Lines.Length > 0)
            {
                // 获取当前按下的键的名称，用逗号分隔
                var pressedKeyNames = pressedKeys.Select(k => GetKeyDisplayName(k)).ToArray();
                string pressedKeysLine = pressedKeyNames.Length > 0 
                    ? $"当前按下的键: {string.Join(", ", pressedKeyNames)}" 
                    : "当前没有按下的键";
                
                // 保存当前光标位置和滚动位置
                int selectionStart = keyLogTextBox.SelectionStart;
                int selectionLength = keyLogTextBox.SelectionLength;
                int firstLineLength = keyLogTextBox.Lines[0].Length;
                
                // 更新第一行
                string[] lines = keyLogTextBox.Lines;
                lines[0] = pressedKeysLine;
                keyLogTextBox.Lines = lines;
                
                // 恢复光标位置和滚动位置
                if (selectionStart > firstLineLength)
                {
                    keyLogTextBox.SelectionStart = selectionStart + (lines[0].Length - firstLineLength);
                }
                else
                {
                    keyLogTextBox.SelectionStart = selectionStart;
                }
                keyLogTextBox.SelectionLength = selectionLength;
                keyLogTextBox.ScrollToCaret();
            }
        }

        private void UpdateHistoryLog(string keyEvent)
        {
            if (historyLogTextBox != null)
            {
                // 添加新的事件到历史记录
                keyHistory.Add($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} - {keyEvent}");
                
                // 只保留最新100条记录（增加容量以支持更好的滚屏显示）
                if (keyHistory.Count > 100)
                {
                    keyHistory.RemoveAt(0);
                }
                
                // 清空并重新显示历史记录（倒序显示，最新的在最上面）
                historyLogTextBox.Clear();
                historyLogTextBox.SelectionFont = new Font("Microsoft YaHei", 9);
                historyLogTextBox.AppendText("历史按键日志（最新100条，实时滚屏显示）：\r\n");
                
                // 倒序显示，最新的在最上面
                for (int i = keyHistory.Count - 1; i >= 0; i--)
                {
                    string eventText = keyHistory[i];
                    
                    // 根据事件类型设置背景色
                    if (eventText.Contains("按下:"))
                    {
                        historyLogTextBox.SelectionBackColor = Color.Yellow; // 黄色背景
                    }
                    else if (eventText.Contains("释放:"))
                    {
                        historyLogTextBox.SelectionBackColor = Color.LightBlue; // 蓝色背景
                    }
                    else
                    {
                        historyLogTextBox.SelectionBackColor = Color.White; // 默认白色背景
                    }
                    
                    // 设置字体大小适应文本框
                    historyLogTextBox.SelectionFont = new Font("Consolas", 9);
                    
                    // 添加文本
                    historyLogTextBox.AppendText(eventText + "\r\n");
                    
                    // 重置背景色
                    historyLogTextBox.SelectionBackColor = Color.White;
                }
                
                // 自动滚屏到顶部显示最新内容
                historyLogTextBox.SelectionStart = 0;
                historyLogTextBox.ScrollToCaret();
                
                // 强制刷新显示以确保滚屏效果
                historyLogTextBox.Refresh();
            }
        }

        private void AutoSaveButton_Click(object sender, EventArgs e)
        {
            if (autoSaveEnabled)
            {
                // 停止自动保存
                autoSaveEnabled = false;
                
                // 更新按钮文本和颜色
                if (sender is Button button)
                {
                    button.Text = "自动保存";
                    button.BackColor = SystemColors.Control;
                }
                
                MessageBox.Show($"自动保存已停止，共保存了 {autoSaveCount} 次日志", "自动保存", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                // 重新开启自动保存
                autoSaveEnabled = true;
                
                // 更新按钮文本和颜色
                if (sender is Button button)
                {
                    button.Text = "停止自动保存";
                    button.BackColor = Color.LightGreen;
                }
                
                MessageBox.Show("自动保存已重新开启，日志将实时保存到应用程序目录下的'键盘测试日志'文件夹中", "自动保存", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void AutoSaveLog()
        {
            if (keyLogTextBox == null)
                return;

            try
            {
                // 获取应用程序所在目录
                string appDirectory = AppDomain.CurrentDomain.BaseDirectory;
                string logDirectory = Path.Combine(appDirectory, "键盘测试日志");
                
                // 确保日志目录存在
                if (!Directory.Exists(logDirectory))
                {
                    Directory.CreateDirectory(logDirectory);
                }
                
                // 创建基于当前日期的日志文件名
                string fileName = Path.Combine(logDirectory, $"键盘测试日志_{DateTime.Now:yyyyMMdd}.txt");
                
                // 获取完整的日志内容
                string logContent = keyLogTextBox.Text;
                
                // 添加历史按键日志信息
                if (historyLogTextBox != null)
                {
                    logContent += $"\n\n历史按键日志：\n{historyLogTextBox.Text}";
                }
                
                // 添加保存时间信息
                logContent = $"键盘测试日志 - 最后更新时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}\n{new string('=', 50)}\n{logContent}";
                
                // 实时保存到文件（覆盖写入，保持最新内容）
                System.IO.File.WriteAllText(fileName, logContent, System.Text.Encoding.UTF8);
                
                autoSaveCount++;
            }
            catch (Exception ex)
            {
                // 自动保存出错时不显示对话框，避免干扰用户操作
                System.Diagnostics.Debug.WriteLine($"自动保存出错：{ex.Message}");
            }
        }

        private void SaveLogButton_Click(object sender, EventArgs e)
        {
            if (keyLogTextBox == null || keyLogTextBox.Text.Length <= 0)
            {
                MessageBox.Show("没有日志内容可保存", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            using (SaveFileDialog saveFileDialog = new SaveFileDialog())
            {
                saveFileDialog.Filter = "文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*";
                saveFileDialog.FilterIndex = 1;
                saveFileDialog.RestoreDirectory = true;
                saveFileDialog.FileName = $"键盘测试日志_{DateTime.Now:yyyyMMdd_HHmmss}.txt";

                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        // 获取完整的日志内容
                        string logContent = keyLogTextBox.Text;
                        
                        // 添加历史按键日志信息
                        if (historyLogTextBox != null)
                        {
                            logContent += $"\n\n历史按键日志：\n{historyLogTextBox.Text}";
                        }
                        
                        // 添加保存时间信息
                        logContent = $"键盘测试日志 - 保存时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}\n{new string('=', 50)}\n{logContent}";
                        
                        // 保存到文件
                        System.IO.File.WriteAllText(saveFileDialog.FileName, logContent, System.Text.Encoding.UTF8);
                        
                        MessageBox.Show($"日志已成功保存到：{saveFileDialog.FileName}", "保存成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($"保存日志时出错：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
        }
    }
}